// ml278
// Copyright (C) 2008 Bjørn Øivind Bjørnsen, Aleksander Gjermundsen, Knut Andre Tidemann, Thomas Hansen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

#include "guimenu.h"
#include "application.h"

using namespace QuickGUI;
using namespace std;

/**
 * constructs the menu, depends on the Application class and need a pre-made KeyBindingsManager instance
 * @param application the application in which this menu is created
 * @param sceneMgr scenemanager used for rendering
 * @param camera camera currently used
 * @param keyMgr precreated KeyBindingsManager instance
 * @param hidden determines if the menu starts hidden
 */
GUIMenu::GUIMenu(Application *application, Ogre::SceneManager *sceneMgr, Ogre::Camera *camera, KeyBindingsManager *keyMgr, bool hidden)
{
        mMenuWindow = 0;
        mOptionsWindow = 0;
	mAboutWindow = 0;
        mKeyBindingsWindow = 0;

        mApplication = application;
        mSceneMgr = sceneMgr;
        mCamera = camera;
        mKeyMgr = keyMgr;

        mTextBoxEvtHndlrs.reserve(mKeyMgr->getNumBindings());
        mTextBoxEvtHndlrs.resize(mKeyMgr->getNumBindings());
        mTextBoxEvtHndlrs[ml278::KEY_FORWARD] = &GUIMenu::evtHndlr_keyForwardChanged;
        mTextBoxEvtHndlrs[ml278::KEY_BACKWARD] = &GUIMenu::evtHndlr_keyBackwardChanged;
        mTextBoxEvtHndlrs[ml278::KEY_YAW_LEFT] = &GUIMenu::evtHndlr_keyYawLeftChanged;
	mTextBoxEvtHndlrs[ml278::KEY_YAW_RIGHT] = &GUIMenu::evtHndlr_keyYawRightChanged;
	mTextBoxEvtHndlrs[ml278::KEY_PITCH_UP] = &GUIMenu::evtHndlr_keyPitchUpChanged;
	mTextBoxEvtHndlrs[ml278::KEY_PITCH_DOWN] = &GUIMenu::evtHndlr_keyPitchDownChanged;
	mTextBoxEvtHndlrs[ml278::KEY_SCREENSHOT] = &GUIMenu::evtHndlr_keyScreenshotChanged;
	mTextBoxEvtHndlrs[ml278::KEY_KEYS_OVERLAY] = &GUIMenu::evtHndlr_keyKeysOverlayChanged;
	mTextBoxEvtHndlrs[ml278::KEY_STATS_OVERLAY] = &GUIMenu::evtHndlr_keyStatsOverlayChanged;
	mTextBoxEvtHndlrs[ml278::KEY_SWITCH_TEXTURE_FILTERING] = &GUIMenu::evtHndlr_keySwitchTextureFilteringChanged;
	mTextBoxEvtHndlrs[ml278::KEY_SWITCH_POLYGON_MODE] = &GUIMenu::evtHndlr_keySwitchPolygonModeChanged;
	mTextBoxEvtHndlrs[ml278::KEY_CAMERA_FIRST_PERSON] = &GUIMenu::evtHndlr_keyCameraFirstPersonChanged;
	mTextBoxEvtHndlrs[ml278::KEY_CAMERA_THIRD_PERSON] = &GUIMenu::evtHndlr_keyCameraThirdPersonChanged;
	mTextBoxEvtHndlrs[ml278::KEY_CAMERA_FREEROAM] = &GUIMenu::evtHndlr_keyCameraFreeroamChanged;
	mTextBoxEvtHndlrs[ml278::KEY_TOGGLE_GUI] = &GUIMenu::evtHndlr_keyToggleGUIChanged;
	mTextBoxEvtHndlrs[ml278::KEY_QUIT] = &GUIMenu::evtHndlr_keyQuitChanged;

        initGUI();

        mKeySettings.reserve(mKeyMgr->getNumBindings());

        if(hidden)
            hide();
        else
            show();
}

/**
 * destructor
 */
GUIMenu::~GUIMenu()
{
        mGUIManager->destroySheet(mSheet);
        delete mWindowSize;
}

/**
 * initializes the menu, creates the GUIManager
 */
void GUIMenu::initGUI()
{
        new QuickGUI::Root();
        QuickGUI::SkinSetManager::getSingleton().loadSkin("qgui",QuickGUI::SkinSet::IMAGE_TYPE_PNG);
        mGUIManager = QuickGUI::Root::getSingleton().createGUIManager(mCamera->getViewport(),"qgui");
        mGUIManager->setSceneManager(mSceneMgr);

        mWindowSize = new QuickGUI::Size(mGUIManager->getViewportWidth(), mGUIManager->getViewportHeight());

        mSheet = mGUIManager->getDefaultSheet();
	mSheet->setSkin("qgui", true); 
	mSheet->setFont("micross.16", true);
        mSheet->disableScrollPane();    // Do not display scroll-bars on the main window
        createMainMenu();
}

/**
 * creates main menu window
 */
void GUIMenu::createMainMenu()
{
        using QuickGUI::Rect;
	using QuickGUI::Point;
	using QuickGUI::Size;

        Size mainMenuSize(160,181);

        mMenuWindow = mSheet->createWindow("mMenuWindow");
	mMenuWindow->hideTitlebar();
        mMenuWindow->allowResizing(false);
	mMenuWindow->setDimensions(Rect((mWindowSize->width / 2.0) - (mainMenuSize.width / 2.0), (mWindowSize->height / 2.0) - (mainMenuSize.height / 2.0), mainMenuSize.width, mainMenuSize.height));

        QuickGUI::Button* resumeButton = mMenuWindow->createButton();
	resumeButton->setDimensions(Rect(8,8,144,30));
	resumeButton->setText("Resume");
        resumeButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&GUIMenu::evtHndlr_resumeApplication,this);
        
        QuickGUI::Button* optionsButton = mMenuWindow->createButton();
	optionsButton->setDimensions(Rect(8,53,144,30));
	optionsButton->setText("Options");
        optionsButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&GUIMenu::evtHndlr_optionsMainMenuButton,this);

	QuickGUI::Button* aboutButton = mMenuWindow->createButton();
	aboutButton->setDimensions(Rect(8,98,144,30));
	aboutButton->setText("About");
	aboutButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&GUIMenu::evtHndlr_aboutMainMenuButton,this);
        
        QuickGUI::Button* exitButton = mMenuWindow->createButton();
	exitButton->setDimensions(Rect(8,143,144,30));
	exitButton->setText("Exit application");
	exitButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&GUIMenu::evtHndlr_exitApplication,this);
}

/**
 * creates options window
 */
void GUIMenu::createOptionsMenu()
{
        using QuickGUI::Rect;
	using QuickGUI::Point;
	using QuickGUI::Size;
        
        QuickGUI::MenuLabel* item;      // Used for combobox items
        
        Size optionsMenuSize(350,310);

        mOptionsWindow = mSheet->createWindow("mOptionsWindow");
        mOptionsWindow->hideTitlebar();
        mOptionsWindow->allowResizing(false);
        mOptionsWindow->setDimensions(Rect((mWindowSize->width / 2.0) - (optionsMenuSize.width / 2.0), (mWindowSize->height / 2.0) - (optionsMenuSize.height / 2.0), optionsMenuSize.width, optionsMenuSize.height));

        QuickGUI::Label* headingLabel = mOptionsWindow->createLabel();
        headingLabel->setDimensions(Rect(0,0,optionsMenuSize.width,30));
        headingLabel->setFont("micross.20", true);
        headingLabel->setText(" Options");
        headingLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);
       
        QuickGUI::Label* keyEditorLabel = mOptionsWindow->createLabel();
        keyEditorLabel->setDimensions(Rect(8,38,135,20));
        keyEditorLabel->setText("Keyboard bindings:");
        keyEditorLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);

        QuickGUI::Button* keyEditorButton = mOptionsWindow->createButton();
        keyEditorButton->setDimensions(Rect(152,38,80,20));
	keyEditorButton->setText("Keybindings editor");
	keyEditorButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&GUIMenu::evtHndlr_keyEditorButton,this);

        QuickGUI::Label* cameraAngleLabel = mOptionsWindow->createLabel();
        cameraAngleLabel->setDimensions(Rect(8,72,135,20));
        cameraAngleLabel->setText("Camera angle:");
        cameraAngleLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);       

        mOptionsCameraAngleCombo = mOptionsWindow->createComboBox();
        mOptionsCameraAngleCombo->setDimensions(Rect(152,72,141,20));
        item = mOptionsCameraAngleCombo->addItem();
        item->setText("3rd person");
        item = mOptionsCameraAngleCombo->addItem();
        item->setText("1st person");
        mOptionsCameraAngleCombo->selectItem(mApplication->getCameraMode());
	mOptionsCameraAngleCombo->addOnSelectionEventHandler(&GUIMenu::evtHndlr_optionsCameraAngleCombo,this);

        QuickGUI::Label* keysOverlayLabel = mOptionsWindow->createLabel();
        keysOverlayLabel->setDimensions(Rect(8,106,135,20));
        keysOverlayLabel->setText("Keys overlay:");
        keysOverlayLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);       

        mOptionsKeysOverlayCombo = mOptionsWindow->createComboBox();
        mOptionsKeysOverlayCombo->setDimensions(Rect(152,106,121,20));
        item = mOptionsKeysOverlayCombo->addItem();
        item->setText("Enabled");
        item = mOptionsKeysOverlayCombo->addItem();
        item->setText("Disabled");
        mOptionsKeysOverlayCombo->selectItem(!(mApplication->getKeysOverlay()));
	mOptionsKeysOverlayCombo->addOnSelectionEventHandler(&GUIMenu::evtHndlr_optionsKeysOverlayCombo,this);

        QuickGUI::Label* statsOverlayLabel = mOptionsWindow->createLabel();
        statsOverlayLabel->setDimensions(Rect(8,140,135,20));
        statsOverlayLabel->setText("Stats overlay:");
        statsOverlayLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);       

        mOptionsStatsOverlayCombo = mOptionsWindow->createComboBox();
        mOptionsStatsOverlayCombo->setDimensions(Rect(152,140,121,20));
        item = mOptionsStatsOverlayCombo->addItem();
        item->setText("Enabled");
        item = mOptionsStatsOverlayCombo->addItem();
        item->setText("Disabled");
        mOptionsStatsOverlayCombo->selectItem(!(mApplication->getStatsOverlay()));
	mOptionsStatsOverlayCombo->addOnSelectionEventHandler(&GUIMenu::evtHndlr_optionsStatsOverlayCombo,this);

        QuickGUI::Label* polygonModeLabel = mOptionsWindow->createLabel();
        polygonModeLabel->setDimensions(Rect(8,174,110,20));
        polygonModeLabel->setText("Polygon mode:");
        polygonModeLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);       

        mOptionsPolygonModeCombo = mOptionsWindow->createComboBox();
        mOptionsPolygonModeCombo->setDimensions(Rect(154,174,182,20));
        item = mOptionsPolygonModeCombo->addItem();
        item->setText("Solid (default)");
        item = mOptionsPolygonModeCombo->addItem();
        item->setText("Wireframe");
        item = mOptionsPolygonModeCombo->addItem();
        item->setText("Points");
        mOptionsPolygonModeCombo->selectItem(mApplication->getPolygonMode());
	mOptionsPolygonModeCombo->addOnSelectionEventHandler(&GUIMenu::evtHndlr_optionsPolygonModeCombo,this);

        QuickGUI::Label* shipControlLabel = mOptionsWindow->createLabel();
        shipControlLabel->setDimensions(Rect(8,208,135,20));
        shipControlLabel->setText("Ship control:");
        shipControlLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);

        mOptionsShipControlCombo = mOptionsWindow->createComboBox();
        mOptionsShipControlCombo->setDimensions(Rect(152,208,121,20));
        item = mOptionsShipControlCombo->addItem();
        item->setText("Enabled");
        item = mOptionsShipControlCombo->addItem();
        item->setText("Disabled");
        mOptionsShipControlCombo->selectItem((unsigned int)0);
	mOptionsShipControlCombo->disable();
	//mOptionsShipControlCombo->addOnSelectionEventHandler(&GUIMenu::evtHndlr_optionsShipControlCombo,this);

        QuickGUI::Label* textureFilteringLabel = mOptionsWindow->createLabel();
        textureFilteringLabel->setDimensions(Rect(8,242,134,20));
        textureFilteringLabel->setText("Texture filtering:");
        textureFilteringLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);       

        mOptionsTextureFilteringCombo = mOptionsWindow->createComboBox();
        mOptionsTextureFilteringCombo->setDimensions(Rect(152,242,141,20));
        item = mOptionsTextureFilteringCombo->addItem();
        item->setText("Bilinear");
        item = mOptionsTextureFilteringCombo->addItem();
        item->setText("Trilinear");
        item = mOptionsTextureFilteringCombo->addItem();
        item->setText("Anistropic");
	Ogre::TextureFilterOptions texOpts = mApplication->getTextureFiltering();
	int selectedTexOpt;
	if(texOpts == TFO_BILINEAR)
		selectedTexOpt = 0;
	else if(texOpts == TFO_TRILINEAR)
		selectedTexOpt = 1;
	else if(texOpts == TFO_ANISOTROPIC)
		selectedTexOpt = 2;
        mOptionsTextureFilteringCombo->selectItem(selectedTexOpt);
	mOptionsTextureFilteringCombo->addOnSelectionEventHandler(&GUIMenu::evtHndlr_optionsTextureFilteringCombo,this);

        QuickGUI::Button* optionsExitButton = mOptionsWindow->createButton();
	optionsExitButton->setDimensions(Rect(8,optionsMenuSize.height-20-8,100,20));
	optionsExitButton->setText("Close");
	optionsExitButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&GUIMenu::evtHndlr_optionsExitButton,this);
}

/**
 * creates about window
 */
void GUIMenu::createAboutWindow()
{
        using QuickGUI::Rect;
	using QuickGUI::Point;
	using QuickGUI::Size;

        Size aboutWindowSize(400,450);

        mAboutWindow = mSheet->createWindow("mAboutWindow");
        mAboutWindow->hideTitlebar();
        mAboutWindow->allowResizing(false);
        mAboutWindow->setDimensions(Rect((mWindowSize->width / 2.0) - (aboutWindowSize.width / 2.0), (mWindowSize->height / 2.0) - (aboutWindowSize.height / 2.0), aboutWindowSize.width, aboutWindowSize.height));

	QuickGUI::Label* headingLabel = mAboutWindow->createLabel();
        headingLabel->setDimensions(Rect(0,0,aboutWindowSize.width,30));
        headingLabel->setFont("micross.20", true);
        headingLabel->setText(" About");
        headingLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);

        QuickGUI::Label* aboutLabel = mAboutWindow->createLabel();
        aboutLabel->setDimensions(Rect(0,30,aboutWindowSize.width,aboutWindowSize.height - 30 - 30));
        //headingLabel->setFont("micross.20", true);
        aboutLabel->setText("ml278 (part of the dissertation \"3D Planetary Surveyor\")\nCopyright (C) 2008 Bjorn Oivind Bjornsen, Aleksander Gjermundsen, Knut Andre Tidemann, Thomas Hansen\n\nThis program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.");
        aboutLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);
       
        QuickGUI::Button* aboutExitButton = mAboutWindow->createButton();
	aboutExitButton->setDimensions(Rect(8,aboutWindowSize.height-20-8,100,20));
	aboutExitButton->setText("Close");
	aboutExitButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&GUIMenu::evtHndlr_aboutExitButton,this);
}

/**
 * creates key bindings window, child of the options window
 */
void GUIMenu::createKeyBindingsMenu()
{
        using QuickGUI::Rect;
	using QuickGUI::Point;
	using QuickGUI::Size;
        
        Size keyBindingsMenuSize(400,550);
        Size labelSize(135,20);
        Size textBoxSize(135,20);
	int labelXPos = 8;
	int textBoxXPos = 152;
        int yPos = 38;

        mKeyBindingsWindow = mSheet->createWindow("mKeyBindingsWindow");
        mKeyBindingsWindow->hideTitlebar();
        mKeyBindingsWindow->allowResizing(false);
        mKeyBindingsWindow->setDimensions(Rect((mWindowSize->width / 2.0) - (keyBindingsMenuSize.width / 2.0), (mWindowSize->height / 2.0) - (keyBindingsMenuSize.height / 2.0), keyBindingsMenuSize.width, keyBindingsMenuSize.height));

        QuickGUI::Label* headingLabel = mKeyBindingsWindow->createLabel();
        headingLabel->setDimensions(Rect(0,0,keyBindingsMenuSize.width,30));
        headingLabel->setFont("micross.20", true);
        headingLabel->setText(" Key bindings");
        headingLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);

        mKeyTextBoxes.empty();

	for(int i=0;i<mKeyMgr->getNumBindings();i++)
	{
		QuickGUI::Label* keyLabel = mKeyBindingsWindow->createLabel();
        	keyLabel->setDimensions(Rect(labelXPos,yPos,labelSize.width,labelSize.height));
        	keyLabel->setText(mKeyMgr->getKeyCodeName((ml278::KeyBindings)i));
        	keyLabel->setHorizontalAlignment(QuickGUI::Label::HA_LEFT);

                mKeyTextBoxes.push_back(mKeyBindingsWindow->createTextBox());
                mKeyTextBoxes[i]->setDimensions(Rect(textBoxXPos,yPos,textBoxSize.width,textBoxSize.height));
		mKeyTextBoxes[i]->setText(mKeyMgr->getKeyCodeString(mKeyMgr->getKey((ml278::KeyBindings)i)));
		// Insert the values from the key manager into local vector
		mKeySettings.push_back(mKeyMgr->getKey((ml278::KeyBindings)i));
		mKeyTextBoxes[i]->addEventHandler(QuickGUI::Widget::EVENT_KEY_DOWN,mTextBoxEvtHndlrs[i],this);
        	mKeyTextBoxes[i]->addEventHandler(QuickGUI::Widget::EVENT_CHARACTER_KEY,mTextBoxEvtHndlrs[i],this);

                yPos += 32;
	}

	mKeyBindingsWindow->setDimensions(Rect((mWindowSize->width / 2.0) - (keyBindingsMenuSize.width / 2.0), (mWindowSize->height / 2.0) - (keyBindingsMenuSize.height / 2.0), keyBindingsMenuSize.width, yPos + 32));

        QuickGUI::Button* keyBindingsOkButton = mKeyBindingsWindow->createButton();
	keyBindingsOkButton->setDimensions(Rect(8,yPos,100,20));
	keyBindingsOkButton->setText("OK");
	keyBindingsOkButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&GUIMenu::evtHndlr_keyBindingsOkButton,this);

	QuickGUI::Button* keyBindingsCancelButton = mKeyBindingsWindow->createButton();
	keyBindingsCancelButton->setDimensions(Rect(120,yPos,100,20));
	keyBindingsCancelButton->setText("Cancel");
	keyBindingsCancelButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&GUIMenu::evtHndlr_keyBindingsCancelButton,this);

	QuickGUI::Button* keyBindingsDefaultsButton = mKeyBindingsWindow->createButton();
	keyBindingsDefaultsButton->setDimensions(Rect(232,yPos,100,20));
	keyBindingsDefaultsButton->setText("Defaults");
	keyBindingsDefaultsButton->addEventHandler(QuickGUI::Widget::EVENT_MOUSE_BUTTON_UP,&GUIMenu::evtHndlr_keyBindingsDefaultsButton,this);
}

/**
 * handles the events from key binding textboxes, called from the evtHndlr-functions. 
 * stores the keybinding locally, does not change the value in the key bindings manager.
 * @param args the event
 * @param binding keybinding to be changed
 */
void GUIMenu::keyTextBoxChanged(const EventArgs& args, ml278::KeyBindings binding)
{
	if(args.eventType == QuickGUI::Widget::EVENT_CHARACTER_KEY)
		mKeyTextBoxes[(unsigned int)binding]->setText(mKeyMgr->getKeyCodeString((OIS::KeyCode)mKeySettings[binding]));
        else
        {
	        const QuickGUI::KeyEventArgs* key = static_cast<const QuickGUI::KeyEventArgs*>(&args);
                mKeySettings[binding] = (OIS::KeyCode)key->scancode;
                mKeyTextBoxes[(unsigned int)binding]->setText(mKeyMgr->getKeyCodeString((OIS::KeyCode)key->scancode));
        }
}

void GUIMenu::evtHndlr_keyForwardChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_FORWARD);
}
void GUIMenu::evtHndlr_keyBackwardChanged(const EventArgs& args)
{
       keyTextBoxChanged(args, ml278::KEY_BACKWARD);
}
void GUIMenu::evtHndlr_keyYawLeftChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_YAW_LEFT);
}
void GUIMenu::evtHndlr_keyYawRightChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_YAW_RIGHT);
}
void GUIMenu::evtHndlr_keyPitchUpChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_PITCH_UP);
}
void GUIMenu::evtHndlr_keyPitchDownChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_PITCH_DOWN);
}
void GUIMenu::evtHndlr_keyScreenshotChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_SCREENSHOT);
}
void GUIMenu::evtHndlr_keyKeysOverlayChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_KEYS_OVERLAY);
}
void GUIMenu::evtHndlr_keyStatsOverlayChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_STATS_OVERLAY);
}
void GUIMenu::evtHndlr_keySwitchTextureFilteringChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_SWITCH_TEXTURE_FILTERING);
}
void GUIMenu::evtHndlr_keySwitchPolygonModeChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_SWITCH_POLYGON_MODE);
}
void GUIMenu::evtHndlr_keyCameraFirstPersonChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_CAMERA_FIRST_PERSON);
}
void GUIMenu::evtHndlr_keyCameraThirdPersonChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_CAMERA_THIRD_PERSON);
}
void GUIMenu::evtHndlr_keyCameraFreeroamChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_CAMERA_FREEROAM);
}
void GUIMenu::evtHndlr_keyToggleGUIChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_TOGGLE_GUI);
}
void GUIMenu::evtHndlr_keyQuitChanged(const EventArgs& args)
{
	keyTextBoxChanged(args, ml278::KEY_QUIT);
}

void GUIMenu::evtHndlr_keyEditorButton(const EventArgs& args)
{
        // If the key bindings window is open for the first time
        if(mKeyBindingsWindow == 0)
                createKeyBindingsMenu();
        // If the key bindings window has been opened before and is being reopened
        else
	{
		// Reinitialize the keybindings from file
		assert(mKeyMgr);
		mKeyMgr->initKeys();	// reload bindings from file
		syncKeyBindingsToManager();
                mKeyBindingsWindow->show();
	}
        mKeyBindingsWindow->bringToFront();

}

void GUIMenu::evtHndlr_optionsCameraAngleCombo(const EventArgs& args)
{
	if(mOptionsCameraAngleCombo->getSelectedItemIndex() == 0) 
	{
		mApplication->setCameraMode(0);
	}
	else
	{
		mApplication->setCameraMode(1);
	}
}

void GUIMenu::evtHndlr_optionsKeysOverlayCombo(const EventArgs& args)
{
	if(mOptionsKeysOverlayCombo->getSelectedItemIndex() == 0) 
	{
		mApplication->showKeysOverlay(true);
	}
	else if(mOptionsKeysOverlayCombo->getSelectedItemIndex() == 1)
	{
		mApplication->showKeysOverlay(false);
	}
}

void GUIMenu::evtHndlr_optionsStatsOverlayCombo(const EventArgs& args)
{
	if(mOptionsStatsOverlayCombo->getSelectedItemIndex() == 0) 
	{
		mApplication->showDebugOverlay(true);
	}
	else if(mOptionsStatsOverlayCombo->getSelectedItemIndex() == 1)
	{
		mApplication->showDebugOverlay(false);
	}
}

void GUIMenu::evtHndlr_optionsPolygonModeCombo(const EventArgs& args)
{
	if(mOptionsPolygonModeCombo->getSelectedItemIndex() == 0 || mOptionsPolygonModeCombo->getSelectedItemIndex() == 1 || mOptionsPolygonModeCombo->getSelectedItemIndex() == 2) 
	{
		mApplication->setPolygonMode(mOptionsPolygonModeCombo->getSelectedItemIndex());
	}
}

void GUIMenu::evtHndlr_optionsTextureFilteringCombo(const EventArgs& args)
{
	if(mOptionsTextureFilteringCombo->getSelectedItemIndex() == 0) 
	{
		mApplication->setTextureFiltering(Ogre::TFO_BILINEAR);
	}
	else if(mOptionsTextureFilteringCombo->getSelectedItemIndex() == 1)
	{
		mApplication->setTextureFiltering(Ogre::TFO_TRILINEAR);
	}
	else if(mOptionsTextureFilteringCombo->getSelectedItemIndex() == 2)
	{
		mApplication->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
	}
}

void GUIMenu::evtHndlr_keyBindingsOkButton(const EventArgs& args)
{
        using QuickGUI::Rect;
	using QuickGUI::Point;
	using QuickGUI::Size;

        // Show error message if unsuccessful
	if(!mKeyMgr->saveAllKeys(&mKeySettings))
	{
                mKeyMgr->setTempAllKeys(&mKeySettings);
		QuickGUI::Window* dialogWindow = mSheet->createWindow("dialogWindow");
		dialogWindow->allowResizing(true);
		dialogWindow->setDimensions(QuickGUI::Rect((mWindowSize->width / 2.0) - (300 / 2.0), (mWindowSize->height / 2.0) - (200 / 2.0), 300, 200));
		dialogWindow->bringToFront();

                QuickGUI::Label* dialogLabel = dialogWindow->createLabel();
                dialogLabel->setDimensions(Rect((dialogWindow->getWidth() / 2) - (284/2),(dialogWindow->getHeight() / 2) - (184/2),284,184));
                dialogLabel->setText("Could not save the keybindings to disk (keys.cfg), check that you have write permission to the executable directory. Setting the keybindings temporarily, they will be reset when the application is restarted or when the keybindings options are reopened.");
	}

        mKeyBindingsWindow->hide();
}

void GUIMenu::evtHndlr_keyBindingsCancelButton(const EventArgs& args)
{
        mKeyBindingsWindow->hide();
}

void GUIMenu::evtHndlr_keyBindingsDefaultsButton(const EventArgs& args)
{
        vector<OIS::KeyCode> defaultKeys = mKeyMgr->getDefaultKeys();
	for(int i=0;i<mKeyMgr->getNumBindings();i++)
	{
		mKeyTextBoxes[i]->setText(mKeyMgr->getKeyCodeString(defaultKeys.at(i)));
		// Insert the values from the key manager into local vector
		mKeySettings[i] = defaultKeys.at(i);
	}
}

void GUIMenu::evtHndlr_resumeApplication(const EventArgs& args)
{
        hide();
}

void GUIMenu::evtHndlr_optionsExitButton(const EventArgs& args)
{
	mOptionsWindow->hide();
}

void GUIMenu::evtHndlr_aboutExitButton(const EventArgs& args)
{
	mAboutWindow->hide();
}

void GUIMenu::evtHndlr_optionsMainMenuButton(const EventArgs& args)
{
        // If the options window is open for the first time
        if(mOptionsWindow == 0)
                createOptionsMenu();
        // If the options window has been opened before and is being reopened
        else
                mOptionsWindow->show();
        mOptionsWindow->bringToFront();
}

void GUIMenu::evtHndlr_aboutMainMenuButton(const EventArgs& args)
{
        // If the options window is open for the first time
        if(mAboutWindow == 0)
                createAboutWindow();
        // If the options window has been opened before and is being reopened
        else
                mAboutWindow->show();
        mAboutWindow->bringToFront();
}

void GUIMenu::evtHndlr_exitApplication(const EventArgs& args)
{
        mApplication->exit();
}

/**
 * syncs the the key bindings manager keys to the locally stored keys, can be used to reload the keys of they are not saved
 * @pre createKeyBindingsMenu() has already been run
*/
void GUIMenu::syncKeyBindingsToManager()
{
	assert(mKeySettings.size() == (unsigned int)mKeyMgr->getNumBindings());
	for(int i=0;i<mKeyMgr->getNumBindings();i++)
	{
		mKeyTextBoxes[i]->setText(mKeyMgr->getKeyCodeString(mKeyMgr->getKey((ml278::KeyBindings)i)));
		// Insert the values from the key manager into local vector
		mKeySettings[i] = (mKeyMgr->getKey((ml278::KeyBindings)i));
	}
}

/**
 * hides the menu
 * @see show()
*/
void GUIMenu::hide()
{
        mGUIManager->getMouseCursor()->hide();
        mMenuWindow->hide();
        if(mOptionsWindow != 0)
                mOptionsWindow->hide();
        if(mKeyBindingsWindow != 0)
                mKeyBindingsWindow->hide();
	if(mAboutWindow != 0)
                mAboutWindow->hide();
        mIsVisible = false;
}

/**
 * shows the menu
 * @see hide()
*/
void GUIMenu::show()
{
        mGUIManager->getMouseCursor()->show();
        mMenuWindow->show();
        mIsVisible = true;
}

/**
 * status of menu
 * @return true if the menu is being shown
*/
bool GUIMenu::isVisible()
{
        return mIsVisible;
}

/**
 * forwards the time to the GUI Manager, provides time to QuickGUI
 * @param time time to be injected
*/
void GUIMenu::injectTime(Ogre::Real time)
{
        mGUIManager->injectTime(time);
}

/**
 * forwards keypresses to the GUI Manager, provides them to QuickGUI
 * @param input key to be injected
*/
void GUIMenu::injectKeyDown(KeyCode input)
{
        mGUIManager->injectKeyDown(input);
}

/**
 * forwards keyreleases to the GUI Manager, provides them to QuickGUI
 * @param input key to be injected
*/
void GUIMenu::injectKeyUp(KeyCode input)
{
        mGUIManager->injectKeyUp(input);
}

/**
 * forwards characters to the GUI Manager, provides them to QuickGUI
 * @param input character to be injected
*/
void GUIMenu::injectChar(char input)
{
        mGUIManager->injectChar(input);
}

/**
 * forwards mouse movements to the GUI Manager, provides them to QuickGUI
 * @param x x position of the mouse movement
 * @param y y position of the mouse movement
*/
void GUIMenu::injectMouseMove(int x,int y)
{
        mGUIManager->injectMouseMove(x,y);
}

/**
 * forwards mouse button presses to the GUI Manager, provides them to QuickGUI
 * @param button mouse button pressed
*/
void GUIMenu::injectMouseButtonDown(const MouseButtonID &button)
{
        mGUIManager->injectMouseButtonDown(button);
}

/**
 * forwards mouse button releases to the GUI Manager, provides them to QuickGUI
 * @param button mouse button released
*/
void GUIMenu::injectMouseButtonUp(const MouseButtonID &button)
{
        mGUIManager->injectMouseButtonUp(button);
}
